"use server";
import { prisma } from "@/lib/db";
import { handlerAction } from "@/lib/handlerAction";
import { getQueryWhere } from "@/lib/sqlQuery";
import { OnlineLog } from "@prisma/client";
import dayjs from "dayjs";
import { execSync } from "child_process";
import fsExtra from "fs-extra";
import fs from "fs";
import path from "path";
// export const runtime = "nodejs";
export const logList = handlerAction<{
  list: OnlineLog;
  total: number;
}>(async (form: any) => {
  let { page = 1, pageSize = 10, timestemp, roleList = "", ...others } = form;
  let whereParams = getQueryWhere(others);
  let where = {
    ...whereParams,
  };

  if (others.time) {
    const times = others.time.split("_");
    where.time = {
      gte: times[0],
      lte: times[1],
    };
  }

  pageSize = Number(pageSize);
  let funs = [
    await prisma.onlineLog.findMany({
      skip: (page - 1) * pageSize, // 跳过前 `offset` 条记录
      take: pageSize, // 取 `pageSize` 条
      where,
      orderBy: {
        time: "desc",
      },
    }),
    await prisma.onlineLog.count({
      where,
    }),
  ];
  const [result, total] = await Promise.all(funs);
  // throw new Error("获取失败");
  // console.log(result);
  return {
    list: result,
    total,
  };
});

export const resetVersion = handlerAction(async (form: UploadFormProp) => {
  const zipPath = path.resolve(process.env.ZIP_LOCATION, form.fileName || "");
  const { servicePath, cliConfig } = form;
  const serviceFilePath = `${servicePath}/dist.zip`;
  let sh = "";
  if (cliConfig) {
    const temp = JSON.stringify(cliConfig) as any;
    const { clearExclude } = temp;
    if (clearExclude === "*") {
      fsExtra.emptyDirSync(servicePath);
    }
    if (clearExclude instanceof Array) {
      removeDirExcept(servicePath, clearExclude);
    }
    sh = temp.sh;
  }

  fsExtra.copyFileSync(zipPath, serviceFilePath);
  execSync(`unzip -o -d  ${servicePath} ${serviceFilePath}`);
  execSync(`rm -rf ${serviceFilePath}`);
  await prisma.onlineLog.create({
    data: {
      appName: form.appName || "",
      remark: `从线上回退到${form.time}`,
      user: form.user || "",
      branch: form.branch || "",
      time: dayjs().format("YYYY-MM-DD HH:mm:ss"),
      fileName: form.fileName || "",
      fileSize: form.fileSize || 0,
      servicePath: servicePath,
    },
  });
  if (sh) {
    execSync(sh, {
      cwd: servicePath,
    });
  }
  // const result = await uploadZip()
  return "回退成功";
});

export type UploadFormProp = {
  appName: string;
  servicePath: string;
  exclude?: string[];
  username?: string;
  password?: string;
  cliConfig?: string;
  remark: string;
  user: string;
  branch: string;
  sh?: string;
  fileName?: string;
  time?: string;
  isLog?: boolean;
  saveZip?: boolean;
  fileSize?: number;
  showLog?: boolean;
  clearExclude?: string | string[];
};

// 删除日志
export const deleteLingLog = handlerAction(async (form: any) => {
  const { id } = form;
  const result = await prisma.onlineLog.delete({
    where: {
      id,
    },
  });
  return result;
});
export const getAllAppName = handlerAction(async (form: any) => {
  const result = await prisma.onlineLog.groupBy({
    by: ["appName"],
  });
  return result;
});
async function removeDirExcept(dirPath: string, excludeDirs: string[]) {
  try {
    const files = fs.readdirSync(path.resolve(dirPath));
    for (const file of files) {
      if (excludeDirs.includes(file)) {
        continue;
      } else {
        const filePath = path.resolve(dirPath, file);
        fsExtra.removeSync(filePath);
      }
    }
  } catch (err) {
    console.error(`Error removing directory: ${err}`);
  }
}
const saveFile = async (blob: File, targetPath: string) => {
  const timeDir = dayjs().format("YYYY-MM-DD");
  const uploadDir = process.env.FILE_STORE + timeDir;
  fs.mkdirSync(uploadDir, {
    recursive: true,
  });
  const type = blob.type.split("/")[1];
  const fileName = new Date().getTime().toString() + "." + type;
  const buffer = Buffer.from(await blob.arrayBuffer());

  fs.writeFileSync(targetPath, buffer as any);
};
export const uploadZip = async (file: File, formBody: UploadFormProp) => {
  const { servicePath } = formBody;
  const serviceFilePath = `${servicePath}/dist.zip`;
  if (
    !(
      servicePath.startsWith("/opt/www") ||
      servicePath.startsWith("/opt/service")
    )
  ) {
    throw Error("当前目录不支持上传");
  }
  if (!fs.existsSync(servicePath)) {
    fs.mkdirSync(servicePath);
  } else {
    // 不需要清空之前的目录
    if (formBody && formBody.clearExclude === "*") {
      fsExtra.emptyDirSync(servicePath);
    }
    if (formBody && formBody.clearExclude instanceof Array) {
      removeDirExcept(servicePath, formBody.clearExclude);
    }
  }
  const timestemp = new Date().getTime();

  if (formBody && formBody.isLog) {
    // 添加上线日志信息
    if (formBody.saveZip) {
      const target = path.join(process.env.ZIP_LOCATION, `${timestemp}.zip`);
      await saveFile(file, path.resolve(target));
    }
    await prisma.onlineLog.create({
      data: {
        appName: formBody.appName || "",
        remark: formBody.remark,
        user: formBody.user || "",
        branch: formBody.branch || "",
        time: dayjs().format("YYYY-MM-DD HH:mm:ss"),
        fileName: formBody.saveZip ? `${timestemp}.zip` : "",
        fileSize: file.size,
        servicePath: servicePath,
        cliConfig: JSON.stringify(formBody),
      },
    });
  }
  await saveFile(file, serviceFilePath);
  execSync(`unzip -o -d  ${servicePath} ${serviceFilePath}`);
  execSync(`rm -rf ${serviceFilePath}`);
  if (formBody.sh) {
    try {
      const result = execSync(formBody.sh, {
        stdio: "pipe",
        cwd: servicePath,
      });
      console.log("PM2 started successfully.");
      console.log("Output:", result.toString());
    } catch (error: any) {
      if (error.status !== 0) {
        console.error("Command failed with exit code:", error.status);
        console.error("Error message:", error.message);
      } else {
        console.error("Unknown error:", error.message);
      }
    }
  }
};
